package com.dji.custom.service;

import com.dji.custom.util.CustomUtil;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.*;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.manage.service.*;
import com.dji.sdk.cloudapi.device.*;
import com.dji.sdk.cloudapi.device.api.AbstractDeviceService;
import com.dji.sdk.cloudapi.livestream.LiveErrorCodeEnum;
import com.dji.sdk.cloudapi.livestream.LiveStartPushRequest;
import com.dji.sdk.cloudapi.livestream.LiveStopPushRequest;
import com.dji.sdk.cloudapi.livestream.api.AbstractLivestreamService;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.SDKManager;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
import com.dji.sdk.mqtt.state.TopicStateRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author sean
 * @version 1.7
 * @date 2023/7/4
 */
@Service
@Slf4j
public class LiveCustomService extends AbstractDeviceService {

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private AbstractLivestreamService abstractLivestreamService;

    @Autowired
    private CustomService customService;

    @Autowired
    private JobCustomService jobCustomService;

    @Autowired
    private PythonCustomService pythonCustomService;

    private static String liveUrl = "http://111.35.143.112:8081/index/api/webrtc?app=live&stream=&type=play";

    @Override
    public void dockLiveStatusUpdate(TopicStateRequest<DockLiveStatus> request, MessageHeaders headers) {
        System.out.println("dockLiveStatusUpdate ,request = " + request.getData());
    }

    @Override
    public void rcLiveStatusUpdate(TopicStateRequest<RcLiveStatus> request, MessageHeaders headers) {
        // RcLiveStatus{liveStatus=[RcLiveStatusData{status=true, videoId=1ZNBJC200C0022/39-0-7/normal-0, videoQuality=AUTO}]}
        if(!Objects.isNull(request.getData())){
            List<RcLiveStatusData> liveStatusDataList = request.getData().getLiveStatus();
            for (RcLiveStatusData data:liveStatusDataList) {
                if(data.getStatus() == true){
                    String[] arr = data.getVideoId().toString().split("/");
                    // 保存直播在线状态redis
                    RedisOpsUtils.setWithExpire(RedisConst.LIVE_STATUS_KEY + arr[0], data, RedisConst.DRC_MODE_ALIVE_SECOND);
                }
            }
        }
        System.out.println("rcLiveStatusUpdate ,request = " + request.getData());
    }

    /** 调用大疆开启直播接口
     * http://127.0.0.1:6789/manage/api/v1/live/streams/start  POST
     * 传参:{
     *     "url": "rtmp://111.35.143.112/live/1699337191583",
     *     "video_id": "1ZNBJC200C0022/39-0-7/normal-0",
     *     "url_type": 1,
     *     "video_quality": 4
     * }
     * 反参:{
     *     "code": 0,
     *     "message": "success",
     *     "data": {
     *         "url": "webrtc://111.35.143.112/live/1ZNBJC200C0022"
     *     }
     * }*/
    public HttpResultResponse customLiveStart(LiveTypeDTO liveParam) {
        // 初始化RTMP直播地址
        String rtmpUrl = liveParam.getUrl();
        // Check if this lens is available live.
        HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(liveParam.getVideoId());
        if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
            return responseResult;
        }

        TopicServicesResponse<ServicesReplyData<String>> response = abstractLivestreamService.liveStartPush(
                SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()), new LiveStartPushRequest()
                        .setUrl(liveParam.getUrl())
                        .setUrlType(liveParam.getUrlType())
                        .setVideoId(new VideoId(liveParam.getVideoId()))
                        .setVideoQuality(liveParam.getVideoQuality()));

        if (!response.getData().getResult().isSuccess()) {
            return HttpResultResponse.error(response.getData().getResult());
        }

        LiveDTO live = new LiveDTO();

        switch (liveParam.getUrlType()) {
            case RTMP:
                live.setUrl(liveParam.getUrl().replace("rtmp", "webrtc"));
                break;
            default:
                return HttpResultResponse.error(LiveErrorCodeEnum.URL_TYPE_NOT_SUPPORTED);
        }
        /* 自定义方法：
        1.替换Zlmediakit的直播URL
        2.发送Custom-mqtt消息-开启直播新增录像信息
        3.保存直播在线地址*/
        // 1.替换Zlmediakit的直播URL、获取直播stream
        String liveUrlStream = CustomUtil.substringAfterLast(liveParam.getUrl(), "live/");
        String webrtcUrl = liveUrl.replace("stream=", "stream=" + liveUrlStream);
        live.setUrl(webrtcUrl);
        String jobId = jobCustomService.getTmpJobId(responseResult.getData().getDeviceSn());
        // 获取sn码
        String[] vedioIdArr = liveParam.getVideoId().split("/");
        String deviceSn = vedioIdArr[0];
        // 2.发送Custom-mqtt消息-开启直播新增录像信息
        customService.liveVideoInsertCustom(liveUrlStream, rtmpUrl, deviceSn,
                "", jobId, "");
        // 3.保存直播在线地址
        RedisOpsUtils.setWithExpire(RedisConst.LIVE_URL_KEY + deviceSn, webrtcUrl, RedisConst.DRC_MODE_ALIVE_SECOND);
        /* 自定义方法结束*/
        return HttpResultResponse.success(live);
    }

    // 检查这个镜头是否可以直播。
    private HttpResultResponse<DeviceDTO> checkBeforeLive(String videoId) {
        if (!StringUtils.hasText(videoId)) {
            return HttpResultResponse.error(LiveErrorCodeEnum.ERROR_PARAMETERS);
        }
        String[] videoIdArr = videoId.split("/");
        // drone sn / enumeration value of the location where the payload is mounted / payload lens
        if (videoIdArr.length != 3) {
            return HttpResultResponse.error(LiveErrorCodeEnum.ERROR_PARAMETERS);
        }

        Optional<DeviceDTO> deviceOpt = deviceService.getDeviceBySn(videoIdArr[0]);
        // Check if the gateway device connected to this drone exists
        if (deviceOpt.isEmpty()) {
            return HttpResultResponse.error(LiveErrorCodeEnum.NO_AIRCRAFT);
        }

        if (DeviceDomainEnum.DOCK == deviceOpt.get().getDomain()) {
            return HttpResultResponse.success(deviceOpt.get());
        }
        List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(
                DeviceQueryParam.builder()
                        .childSn(videoIdArr[0])
                        .build());
        if (gatewayList.isEmpty()) {
            return HttpResultResponse.error(LiveErrorCodeEnum.NO_FLIGHT_CONTROL);
        }

        return HttpResultResponse.success(gatewayList.get(0));
    }

    /** 调用大疆关闭直播接口
     * http://127.0.0.1:6789/manage/api/v1/live/streams/stop  POST
     * 传参:{
     *   "video_id": "4TADL5400100DU/165-0-7/normal-0"
     * }
     * 反参:{
     *     "code": 0,
     *     "message": "success",
     *     "data": ""
     * }*/
    public HttpResultResponse customLiveStop(String videoId) {
        HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(videoId);
        if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
            return responseResult;
        }

        TopicServicesResponse<ServicesReplyData> response = abstractLivestreamService.liveStopPush(
                SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()), new LiveStopPushRequest()
                        .setVideoId(new VideoId(videoId)));
        if (!response.getData().getResult().isSuccess()) {
            return HttpResultResponse.error(response.getData().getResult());
        }

        try {
            // 删除直播在线地址
            RedisOpsUtils.del(RedisConst.LIVE_URL_KEY + responseResult.getData().getChildDeviceSn());
            // 删除直播在线状态
            RedisOpsUtils.del(RedisConst.LIVE_STATUS_KEY + responseResult.getData().getChildDeviceSn());
        }catch (Exception e){
            e.printStackTrace();
        }

        // 通知远程关闭直播
        pythonCustomService.stopPythonAi(videoId, responseResult.getData().getChildDeviceSn());

        return HttpResultResponse.success();
    }


}
